using System.Reflection;
using Autofac;
using Autofac.Extras.DynamicProxy;
using KL.Core.Common.infrastructure;
using KL.Core.Common.MyOptions;
using KL.Core.Common.Utils;
using KL.Core.Extensions.AOP;
using KL.Standard.Domain.MessageQueue;
using KL.Standard.Model.Attribute;
using KL.Standard.Model.Tenants;
using KL.Standard.RabbitMQ;
using KL.Standard.Repositories.DBContext;
using Microsoft.Extensions.Configuration;

namespace KL.Core.Extensions;

public class AutofacModuleRegister : Autofac.Module
{
    private readonly IConfiguration _configuration;
    public AutofacModuleRegister(IConfiguration configuration)
    {
        _configuration = configuration;
    }
    /*
    1、看是哪个容器起的作用，报错是什么
    2、三步走导入autofac容器
    3、生命周期，hashcode对比，为什么controller里没变化
    4、属性注入
    */
    protected override void Load(ContainerBuilder builder)
    {
        var basePath = AppContext.BaseDirectory;

        var servicesDllFile = Path.Combine(basePath, "KL.Standard.Services.dll");
        var repositoryDllFile = Path.Combine(basePath, "KL.Standard.Repositories.dll");
        
        #region 配置数据库上下文
        var dbConfigs = _configuration.GetSection("DataSource").Get<IEnumerable<DBConfigEntity>>();
        var tenantConfigs = new TenantDataSourcConfig();
        foreach (var dbConfig in dbConfigs)
        {
            tenantConfigs.Add(dbConfig.dataSourceTag, dbConfig.connectionStr);
        }
        builder.Register(c => tenantConfigs).As<TenantDataSourcConfig>().SingleInstance();
        builder.RegisterType<MyDbContext>().InstancePerLifetimeScope();
        
        #endregion
        #region 注入AOP
        //用于Repository事务
        builder.RegisterType<TransactionInterceptor>()
            .InstancePerLifetimeScope();
        //.PropertiesAutowired();
        //用于Svc缓存
        builder.RegisterType<CacheInterceptor>()
            .InstancePerLifetimeScope();
        //.PropertiesAutowired();
        #endregion
        
        
        #region 基础Repository& Service
        //var aopTypes = new List<Type>() { typeof(ServiceAOP), typeof(TranAOP) };
        // var aopTypes = new List<Type>() { typeof(ServiceAOP) };
        // builder.RegisterType<ServiceAOP>();
        //builder.RegisterType<TranAOP>();

        // builder.RegisterGeneric(typeof(BaseSRepository<>)).As(typeof(IBaseSRepository<>))
        //     .InstancePerDependency(); //注册仓储
        // builder.RegisterGeneric(typeof(BaseSvc<,>)).As(typeof(IBaseSvc<,>))
        //     .EnableInterfaceInterceptors()
        //     .InterceptedBy(aopTypes.ToArray())
        //     .InstancePerDependency(); //注册服务
        #endregion
        #region 获取 Service.dll 程序集服务，并注册
        var assemblysServices = Assembly.LoadFrom(servicesDllFile);
        //没有缓存的
        builder.RegisterAssemblyTypes(assemblysServices)
            .Where(t => t.Name.EndsWith("Svc")&&t.GetCustomAttributes<AOPAttribute>(true).FirstOrDefault()==null)
            .AsImplementedInterfaces()
            .InstancePerDependency()
            .PropertiesAutowired();
        //启用缓存
        builder.RegisterAssemblyTypes(assemblysServices)
            .Where(t => t.Name.EndsWith("Svc")&&t.GetCustomAttributes<AOPAttribute>(true).FirstOrDefault()!=null)
            .AsImplementedInterfaces()
            .InstancePerDependency()
            .PropertiesAutowired()
            .EnableInterfaceInterceptors()
            .InterceptedBy(typeof(CacheInterceptor));
        #endregion
        #region 获取 Repository.dll 程序集服务，并注册
        var assemblysRepository = Assembly.LoadFrom(repositoryDllFile);
        var types = assemblysRepository.GetTypes().Where(t => t.Name.EndsWith("Repository"));
        builder.RegisterAssemblyTypes(assemblysRepository)
            .Where(t => t.Name.EndsWith("Repository"))
            .AsImplementedInterfaces()
            .PropertiesAutowired()
            .InstancePerDependency()
            .EnableInterfaceInterceptors()
           .InterceptedBy(typeof(TransactionInterceptor));;
        #endregion
    
        #region Message Queue 操作类

        if (AppSettings.app(new string[] { "RabbitMq", "Enabled" }).ObjToBool())
        {
            builder.RegisterGeneric(typeof(BaseQueueProductor<>)).As(typeof(IBaseQueueProductor<>))
                .PropertiesAutowired()
                .InstancePerDependency(); //注册生产者
            builder.RegisterGeneric(typeof(BaseQueueConcumer<>)).As(typeof(IBaseQueueConcumer<>))
                .PropertiesAutowired()
                .InstancePerDependency(); //注册消费者
        }

        #endregion
        
        #region MongoBD
        var mongoDbOptions = _configuration.GetSection("MongoDB").Get<MongoDBOptions>();
        if (mongoDbOptions?.Enabled ?? false)
        {
            var mongoDbRepositoryDllFile = Path.Combine(basePath, "KL.Standard.Mongo.Repositories.dll");
            var assemblysMongoDbRepo = Assembly.LoadFrom(mongoDbRepositoryDllFile);
            //没有缓存的
            builder.RegisterAssemblyTypes(assemblysMongoDbRepo)
                .Where(t => t.Name.EndsWith("Repository"))
                .AsImplementedInterfaces()
                .InstancePerDependency()
                .PropertiesAutowired();
        }

        #endregion
        // builder.RegisterType<UnitOfWorkManage>().As<IUnitOfWorkManage>()
        //     .AsImplementedInterfaces()
        //     .InstancePerLifetimeScope()
        //     .PropertiesAutowired();
    }
}